var Chart = $ZClass.extend({
	construct : function(id,config) {
		this.el = $Z('#'+id);
		this.config = $.extend({
			width: this.el.zmwidth(),
			height: this.el.zmheight(),
			yStep:8,
			paddingL:50,
			paddingR:85,
			paddingB:100,
			paddingT:30,
			colorArr : ["#62c9a5", "#bdc9d3", "#74ade5", "#7798BF",
			"#aaeeee", "#ff0066", "#eeaaee","#55BF3B", "#DF5353", "#7798BF", "#aaeeee"]
		},config);

		this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
		this.el.append(this.svg);
		this.sizeSvg();
	},
	setSvg : function(width,height) {
		this.config.width = width;
		this.config.height = height;
		this.sizeSvg();
	},
	sizeSvg : function() {
		this.svg.setAttribute('width', this.config.width||'100%');
	    this.svg.setAttribute('height', this.config.height||'100%');
		//防止表格显示不全
		this.config.paddingT = Math.floor(this.config.height/10);
	   	this.config.width = this.config.width - this.config.paddingR - this.config.paddingL;
		this.config.height = this.config.height -this.config.paddingB - this.config.paddingT;
	},
	clearGmain : function() {
    	if (this.gMain) {
    		$(this.gMain).remove();
    	}
	},
	initGmain : function() {
		this.gMain = this._makeSVG('g');
	   	this.svg.appendChild(this.gMain);
	},
	draw : function(data){
		this.axisX = data.xValue;
		this.dataset = data.yValue;
		this.yKeyArr = [];
		for(var item in this.dataset){
			this.yKeyArr.push(item);
		}
		if(this.yKeyArr.length > 2) {
			this.column();
		} else if(this.yKeyArr.length == 1) {
			this.line();
		} else if(this.yKeyArr.length == 2) {
			this.bar();
		}
	},
	_makeSVG : function(tag,attrs,text_content) {
		var el= document.createElementNS('http://www.w3.org/2000/svg', tag);
		if(attrs) {
			for (var k in attrs)
            	el.setAttribute(k, attrs[k]);
		}
        if(text_content){
            el.textContent = text_content;
        }
        return el;
	},
	_sortNumber : function (a,b) {
	    return a-b;
	},
	initValueY : function(type) {
		var dataset=this.dataset;
		this.pointTotal = [];
		this.pointTotal.length = 0;
		if(type === 'column') {
			this.yMax=this.yMin=0;
			var pointTotal = [];
			for (var i=0,len=this.yKeyArr.length;i< len;i++) {
				var points = dataset[this.yKeyArr[i]];
				for(var j=0,leng=points.length;j< leng;j++){
					if(!i) {
						pointTotal[j] = points[j];
					} else {
						pointTotal[j] += points[j];
					}
				}
			}
			var arrBack = pointTotal.concat().sort(this._sortNumber),
				arrBackLen = arrBack.length;
			this.yMax = Math.ceil(Math.max(this.yMax,arrBack[arrBackLen-1]));
			this.pointTotal = pointTotal;
		} else {
			this.yMax=this.yMin=dataset[this.yKeyArr[0]][0];
			for (var itm in dataset) {
				var points = dataset[itm],
					arrBack = points.concat().sort(this._sortNumber),
					arrBackLen = arrBack.length,
					yMax = arrBack[arrBackLen-1],
					yMin = arrBack[0];
				this.yMax = Math.ceil(Math.max(yMax,this.yMax));
				this.yMin = Math.floor(Math.min(yMin,this.yMin));
			}
		}
		this.yRange = Math.ceil(this.yMax - this.yMin);
		if(this.yRange < this.config.yStep) {
			this.yRange = this.config.yStep;
			this.singleStepY = 1;
		} else {
			this.singleStepY = Math.ceil(this.yRange/(this.config.yStep-1));
		}
		this.yRatio = Math.floor(this.config.height)/this.yRange;
		this.config.realHeight = this.yRatio*(this.config.yStep-1)*this.singleStepY;
		this.config.realPaddingT = this.config.paddingT + this.config.height - this.config.realHeight;
	},
	initAxisX : function(type) {
		if(type === 'line') {
			var chartType = 1;
		} else {
			var chartType = 0;
		}
		var gWrap = this._makeSVG('g',{'class':'axis axisX','transform': 'translate('+this.config.paddingL+',' + (this.config.height +this.config.paddingT)+')'}),
			lineWrap = this._makeSVG('g',{'class':'baseLineY'}),
			titleX = this.axisX,
			axisLength = titleX.length-chartType,
			stepX = this.config.width/axisLength,
			x= 0;
		this.singleStepX = stepX;
		for (var i = 0; i <= axisLength; i++) {
			var tickText = this._makeSVG('text',{'dy':17},titleX[i]),
				tickLine = this._makeSVG('line',{'y2':4,'stroke':'#ccc'}),
				tick = this._makeSVG('g',{'transform':'translate(' + x + ',0)'});

			$(tick).append(tickLine);
			$(tick).append(tickText);
			$(gWrap).append(tick);
			x += stepX;
			/*baseLineY*/
			var baseLine = this._makeSVG('path',{
				'd':'M'+(this.config.paddingL+(i*this.singleStepX))+','+(this.config.height + this.config.paddingT)+' V'+(this.config.realPaddingT-5),
				'class':'axisLine',
				'stroke':'#ddd'
			});
			lineWrap.appendChild(baseLine);
		}
		this.gMain.appendChild(gWrap);
		this.gMain.appendChild(lineWrap);
		/*保证文字绝对居中*/
		var tickTextArr = $('text',$('.axisX',this.el)[0]);
		for (var i=0,len=tickTextArr.length;i< len;i++) {
			fontWidth = tickTextArr[i].getBBox().width;
			if (fontWidth > (stepX*0.8)) {
				var degree = Math.acos(stepX/fontWidth%Math.PI)/Math.PI*180;
				if(type === 'line') {
					$(tickTextArr[i]).attr({'transform':'rotate('+degree+')'});
				} else  {
					$(tickTextArr[i]).attr({'transform':'rotate('+degree+') translate('+(stepX/2)+','+(-stepX/2)+')'});
				}
			} else {
				tickTextArr[i].setAttribute('transform','translate(' + ((1-chartType)*stepX/2-fontWidth/2) + ',0)');
			}
		}
	},
	baseLineX : function() {
		var lineWrap = this._makeSVG('g',{'class':'baseLineX'}),
			lineValue = this._makeSVG('g',{'class':'baseLineValueX'});

		for (var i=0;i< this.config.yStep;i++) {
			var baseLine = this._makeSVG('path',{
				'd':'M'+(this.config.paddingL-5)+','+(this.config.height+this.config.paddingT-i*this.singleStepY*this.yRatio)+' H'+(this.config.width+this.config.paddingL+5),
				'class':'axisLine',
				'stroke':'#ddd'
			});
			var baseLineValue = this._makeSVG('text',{
				'text-anchor':'end',
				'transform':'translate('+(this.config.paddingL-10)+','+(this.config.height+this.config.paddingT-i*this.singleStepY*this.yRatio)+')'
			},(this.singleStepY*i+this.yMin).toString());
			lineWrap.appendChild(baseLine);
			lineValue.appendChild(baseLineValue);
		}
		this.gMain.appendChild(lineWrap);
		this.gMain.appendChild(lineValue);
	},
	generateLine : function() {
		var dataset = this.dataset;
		for (var i=0,len=this.yKeyArr.length;i< len;i++) {
			var color = this.config.colorArr[i];
			this._drawLine(dataset[this.yKeyArr[i]],color);
		}
	},
	_drawLine : function(points,color) {
		var gWrap = this._makeSVG('g',{'class':'Line'}),
			dataline = 'M ',
			root = this,
			cordinates = [];
		/*Pot*/
		for (var i=0,len=points.length;i< len;i++) {
			var x=i*this.singleStepX+this.config.paddingL,
				y=this.config.height+this.config.paddingT-(points[i]-this.yMin)*this.yRatio,
				pointCord = {},
				splinePath = [];
			pointCord.plotX = x;
			pointCord.plotY = y;
			cordinates.push(pointCord);
			var gSpot = this._makeSVG('circle',{
				'r': 3,
				'cx': x,
				'cy': y,
				'fill': color
			});
			$(gWrap).append(gSpot);
		}
		/*spline*/
		$.each(cordinates,function (i,el) {
			splinePath.push(root._getSpline(cordinates,el,i));
		});
		var spline = this._makeSVG('path',{
			'd':splinePath.join(''),
			'stroke':color,
			'fill':'none',
			'stroke-width':2
		});
		gWrap.appendChild(spline);
		this.gMain.appendChild(gWrap);
	},
	_getSpline : function (segment, point, i) {
		var smoothing = 1.5, // 1 means control points midway between points, 2 means 1/3 from the point, 3 is 1/4 etc
			denom = smoothing + 1,
			plotX = point.plotX,
			plotY = point.plotY,
			lastPoint = segment[i - 1],
			nextPoint = segment[i + 1],
			leftContX,
			leftContY,
			rightContX,
			rightContY,
			ret;
		// find control points
		if (lastPoint && nextPoint) {
			var lastX = lastPoint.plotX,
				lastY = lastPoint.plotY,
				nextX = nextPoint.plotX,
				nextY = nextPoint.plotY,
				correction;
			leftContX = (smoothing * plotX + lastX) / denom;
			leftContY = (smoothing * plotY + lastY) / denom;
			rightContX = (smoothing * plotX + nextX) / denom;
			rightContY = (smoothing * plotY + nextY) / denom;
			// have the two control points make a straight line through main point
			correction = ((rightContY - leftContY) * (rightContX - plotX)) /
				(rightContX - leftContX) + plotY - rightContY;
			leftContY += correction;
			rightContY += correction;
			// to prevent false extremes, check that control points are between
			// neighbouring points' y values
			if (leftContY > lastY && leftContY > plotY) {
				leftContY = Math.max(lastY, plotY);
				rightContY = 2 * plotY - leftContY; // mirror of left control point
			} else if (leftContY < lastY && leftContY < plotY) {
				leftContY = Math.min(lastY, plotY);
				rightContY = 2 * plotY - leftContY;
			}
			if (rightContY > nextY && rightContY > plotY) {
				rightContY = Math.max(nextY, plotY);
				leftContY = 2 * plotY - rightContY;
			} else if (rightContY < nextY && rightContY < plotY) {
				rightContY = Math.min(nextY, plotY);
				leftContY = 2 * plotY - rightContY;
			}
			// record for drawing in next point
			point.rightContX = rightContX;
			point.rightContY = rightContY;
		}
		// moveTo or lineTo
		if (!i) {
			ret = 'M '+plotX+','+plotY;
		} else { // curve from last point to this
			ret = 'C '+(lastPoint.rightContX || lastPoint.plotX)+','+(lastPoint.rightContY || lastPoint.plotY)+' '+(leftContX || plotX)+','+(leftContY || plotY)+' '+plotX+','+plotY;
			lastPoint.rightContX = lastPoint.rightContY = null; // reset for updating series later
		}
		return ret;
	},
	generateHzone : function() {
		var	titleX = this.axisX,
			axisLength = titleX.length,
			gWrap = this._makeSVG('g',{'class':'Hzone'}),
			dataset = this.dataset;
		
		for (var j=0;j< axisLength;j++) {
			var Hseries = this._makeSVG('g',{'class':'Hseries'});
			/*hpot*/
			for (var i=0,len=this.yKeyArr.length;i< len;i++) {
				var color = this.config.colorArr[i],
					dataLen = dataset[this.yKeyArr[i]],
					points = this.dataset[this.yKeyArr[i]],
					x = j*this.singleStepX+this.config.paddingL,
					y = this.config.height+this.config.paddingT-(points[j]-this.yMin)*this.yRatio;

				var hSpot = this._makeSVG('circle',{
						'class':'hpot',
						'r': 4,
						'cx': x,
						'cy': y,
						'stroke': color,
						'stroke-width': 2,
						'fill': '#fff',
						'display':'none'
					});
				Hseries.appendChild(hSpot);
			}
			/*hzone rectangle*/
			var rect = this._makeSVG('rect',{
				'class':'rect',
				'x': (this.config.paddingL+((j-1/2)*this.singleStepX)),
				'y': (this.config.realPaddingT),
				'width': this.singleStepX,
				'height': (this.config.realHeight),
				'fill': 'transparent'
			});
			Hseries.appendChild(rect);
			gWrap.appendChild(Hseries);
		}
		this.gMain.appendChild(gWrap);
	},
	_clearSvgChilds : function(nodeName) {
		while ( nodeName.firstChild ) {
	        nodeName.removeChild( nodeName.firstChild );
	    }
	},
	setTooltip : function(type,className,innerEle) {
		var Hlist = $('.'+className,this.el),
			toolTip = this._makeSVG('g',{'class':'toolTip'}),
			toolTipBg = this._makeSVG('rect'),
			toolTipContent = this._makeSVG('text'),
			titleX = this.axisX,
			dataset = this.dataset,
			toolTipPad = 10,
			valueX = valueY = 0,
			toolTipH = toolTipW = 0,
			root = this;
		toolTip.appendChild(toolTipBg);
		toolTip.appendChild(toolTipContent);
		this.gMain.appendChild(toolTip);
		$.each(Hlist,function(i,el) {
			$(el).on("mouseenter", pathMouseEnter(i))
				 .on("mouseleave", pathMouseLeave);
		});
		function pathMouseEnter(i) {
			return function() {
				var toolTipCordY = 0,
					toolTipCordX = 0,
					toolTipValue = [],
					innerEles = $(innerEle,this);
				if(type === 'bar' || type === 'column') {
					$.each(innerEles,function(j,el) {
						$(el).attr({'opacity':1});
						toolTipCordY += parseInt($(el).attr('height'));
						toolTipCordX = parseInt(root.config.paddingL + (i+1/2)*root.singleStepX);
						toolTipValue.push(root.dataset[root.yKeyArr[j]][i]);
					});
					toolTipCordY = root.config.height +root.config.paddingT- toolTipCordY/innerEles.length;
				} else if(type === 'line'){
					$.each(innerEles,function(j,el) {
						$(el).show();
						toolTipCordY += parseInt($(el).attr('cy'));
						toolTipCordX = parseInt($(el).attr('cx'))+10;
						toolTipValue.push(root.dataset[root.yKeyArr[j]][i]);
					});
					toolTipCordY = toolTipCordY/innerEles.length;
				}
				updateToolTip(i,toolTipCordX,toolTipCordY,toolTipValue);
			}
		}
		function updateToolTip(i,toolTipCordX,toolTipCordY,toolTipValue) {
			/*clear toolTipContent everytime*/
			root._clearSvgChilds(toolTipContent);
			/* x value */
			var toolTipValueTitle = root._makeSVG('tspan',{'font-size':'18px','font-weight':'bold'},titleX[i]);
			toolTipContent.appendChild(toolTipValueTitle);
			$(toolTip).attr({'fill':'#000'})
					  .show()
					  .on("mouseenter", function() {
							$(this).show();
			});
			/* toolTipContent */
			for(var j = 0,len = toolTipValue.length,k=len-1;(j< len && k >= 0);j++,k--) {
				if(type === 'column') {
					index = k;
				} else {
					index = j;
				}
				var toolTipCircle = root._makeSVG('tspan',{'x':0,'dy':15,'font-size':'20px','style':'fill:'+root.config.colorArr[index]},'●');
				toolTipContent.appendChild(toolTipCircle);
				var toolTipData = root._makeSVG('tspan',{'x':15,'dy':0});
				if(root.pointTotal.length > 0) {
					toolTipData.textContent = root.yKeyArr[index] +' '+ (Math.round(toolTipValue[index]/root.pointTotal[i]*100)+'%')
				} else {
					toolTipData.textContent = root.yKeyArr[index] +' '+ toolTipValue[index].toString();
				}
				toolTipContent.appendChild(toolTipData);
			}
			toolTipH = toolTipContent.getBBox().height+toolTipPad*2;
			toolTipW = toolTipContent.getBBox().width+toolTipPad*2;
			$(toolTipBg).attr({
				'rx':'5',
				'ry':'5',
				'width':toolTipW,
				'height':toolTipH,
				'fill':'#000'
			});
			/* move toolTipContent to center*/
			$(toolTipContent).attr({
				'transform':'translate('+toolTipPad+','+(toolTipPad+10)+')',
				'fill':'#eee'
			});
			/* keep tooltip in wrap */
			if(toolTipCordX > root.config.paddingL+root.config.width) {
				toolTipCordX -= toolTipW*1.4;
			}
			if(toolTipCordY < root.config.paddingT) {
				toolTipCordY += toolTipH*1.4;
			} else if((toolTipCordY+toolTipH) > (root.config.paddingT+root.config.height)) {
				toolTipCordY -= toolTipH*1.2;
			}
			toolTip.setAttribute('transform','translate('+toolTipCordX+','+toolTipCordY+')');
		}
		function pathMouseLeave() {
			$.each($(innerEle,this),function(i,el) {
				if(type === 'bar' || type === 'column') {
					$(el).attr({'opacity':root.barOpacity});
				} else if(type === 'line') {
					$(el).hide();
				}
			});
			$(toolTip).hide();
		}
	},
	generateBar : function() {
		var	titleX = this.axisX,
			axisLength = titleX.length,
			gWrap = this._makeSVG('g',{'class':'Bar'}),
			dataset = this.dataset;
		
		for (var j=0;j< axisLength;j++) {
			var BarSeries = this._makeSVG('g',{'class':'BarSeries'});
			/*bar rect*/
			for (var i=0,len=this.yKeyArr.length;i< len;i++) {
				var color = this.config.colorArr[i],
					dataLen = dataset[this.yKeyArr[i]],
					points = this.dataset[this.yKeyArr[i]],
					barWidth = this.singleStepX*(1-0.2)/len,
					barHeight = (points[j]-this.yMin)*this.yRatio,
					barGap = 4;
				this.barOpacity = 0.9;
				var bar = this._makeSVG('rect',{
					'x': (this.config.paddingL+(barWidth+barGap)*i+this.singleStepX*j+this.singleStepX/10-barGap/2),
					'y': this.config.height+this.config.paddingT-barHeight,
					'width': barWidth,
					'height': barHeight,
					'stroke': color,
					'stroke-width': 2,
					'fill': color,
					'opacity': this.barOpacity
				});
				BarSeries.appendChild(bar);
			}
			gWrap.appendChild(BarSeries);
		}
		this.gMain.appendChild(gWrap);
	},
	generateColumn : function() {
		var	titleX = this.axisX,
			axisLength = titleX.length,
			gWrap = this._makeSVG('g',{'class':'Column'}),
			dataset = this.dataset,
			columnTotalH = [];
		
		for (var j=0;j< axisLength;j++) {
			var ColumnSeries = this._makeSVG('g',{'class':'ColumnSeries'});
			/*bar rect*/
			for (var i=0,len=this.yKeyArr.length;i< len;i++) {
				var color = this.config.colorArr[i],
					dataLen = dataset[this.yKeyArr[i]],
					points = this.dataset[this.yKeyArr[i]],
					columnWidth = this.singleStepX*2/3,
					columnHeight = (points[j]-this.yMin)*this.yRatio,
					barGap = 4;
				if(!i) {
					columnTotalH[j] = columnHeight;
				} else {
					columnTotalH[j] += columnHeight;
				}
				this.barOpacity = 0.7;
				var bar = this._makeSVG('rect',{
					'x': (this.config.paddingL+(j+1/2-1/3)*this.singleStepX),// 1/3 => columnWidth/2
					'y': (this.config.height+this.config.paddingT-columnTotalH[j]),
					'width': columnWidth,
					'height': columnHeight,
					'stroke': color,
					'stroke-width': 2,
					'fill': color,
					'opacity': this.barOpacity
				});
				ColumnSeries.appendChild(bar);
			}
			gWrap.appendChild(ColumnSeries);
			var columnValue = this._makeSVG('text',{
				'x':(this.config.paddingL+(j+1/2)*this.singleStepX),
				'y':(this.config.height+this.config.paddingT-columnTotalH[j]-5)
			},this.pointTotal[j]);
			ColumnSeries.appendChild(columnValue);
			gWrap.appendChild(ColumnSeries);
		}
		this.gMain.appendChild(gWrap);
		/*保证文字绝对居中*/
		columnSeries_ele = $('.ColumnSeries',this.el);
		for (var j=0,len=columnSeries_ele.length;j< len;j++) {
			var tickTextArr = $('text',columnSeries_ele[j])[0];
			fontWidth = tickTextArr.getBBox().width;
			tickTextArr.setAttribute('x',tickTextArr.getAttribute('x') - fontWidth/2);
		}
	},
	line : function() {
		this.clearGmain();
		this.initGmain();
		this.initValueY();
		this.initAxisX('line');
		this.baseLineX();
		this.generateLine();
		this.generateHzone();
		this.setTooltip('line','Hseries','circle');
	},
	bar : function() {
		this.clearGmain();
		this.initGmain();
		this.initValueY();
		this.initAxisX();
		this.baseLineX();
		this.generateBar();
		this.setTooltip('bar','BarSeries','rect');
	},
	column : function() {
		this.clearGmain();
		this.initGmain();
		this.initValueY('column');
		this.initAxisX();
		this.baseLineX();
		this.generateColumn();
		this.setTooltip('column','ColumnSeries','rect');
	}
});

if(typeof Ext != 'undefined') {
	Ext.ns('Ext.ux');
	Ext.ux.Chart = Ext.extend(Ext.Panel,  {
	    afterRender : function(ct, position){
	        Ext.ux.Chart.superclass.afterRender.call(this, ct, position);
		
	    	this.chart = new Chart(this.body.id);
	    },

	    onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
	        Ext.Panel.superclass.onResize.call(this, adjWidth, adjHeight, rawWidth, rawHeight);

	        this.chart.setSvg(adjWidth,adjHeight);
	        if(this.chartData) {
				this.setValue(this.chartData);
	    	}
	    },
	    
	    setValue: function(v,communitys_list) {
	    	var chartJson = new Object();
			    chartJson.xValue = [];
			    chartJson.yValue = new Object();

			function trans(obj) {
				for (var itm in v) {
				    chartJson.xValue.push(itm);
				    if(communitys_list) {
				    	for (var i=0,len=v[itm].length;i< len;i++) {
				    		for (var item in v[itm][i]) {
						    	var community_name = ZM.id2name(item,communitys_list);
								if(!chartJson.yValue[community_name]) {
									chartJson.yValue[community_name] = [];
								}
							}
					    	chartJson.yValue[community_name].push(parseInt(v[itm][i][item]));
					    }
				    } else {
					    for (var item in v[itm]) {
					      if(!chartJson.yValue[item]) {
					        chartJson.yValue[item] = [];
					      }
					      chartJson.yValue[item].push(parseInt(v[itm][item]));
					    }
					}
				}
			}
			if(v != this.chartData) {
				trans(v);
	        	this.chartData = chartJson;
	        }
	        this.chart.draw(this.chartData);
	    }
	});

	Ext.reg('chart', Ext.ux.Chart);
}